<?php

namespace Core;

/**
 * 路由控制
 *
 * @author lxc
 */
class Route
{

	protected $controller = '';
	protected $action = '';

	private static function init()
	{
		$GLOBALS['static_file_mtime'] = [];
	}

	public static function run(Request &$request)
	{
		self::init();

		$fid = $request->get('fid');

		//处理静态资源文件
		$send_file_path = $request->get('send_file_path');
		if (!empty($send_file_path))
			return self::send_file($fid, $send_file_path);

		$controller = $request->get('controller');
		$action = $request->get('action');
		$response = new Response();

		//程序错误检查
		set_error_handler(function() use($fid) {
			$err = debug_backtrace();
			$args = $err[0]['args'];
			self:: send_error_response($fid, '501 system error', "系统错误");
			$string = '系统错误 : [Error : ' . $args[1] . ' in file ' . $args[2] . ' on line ' . $args[3] . ']';
			if (isset($args[4]) && isset($args[4]['backtrace']) && isset($args[4]['backtrace'][0]))
				$string .= '[' . $args[4]['backtrace'][0]['file'] . ' on line ' . $args[4]['backtrace'][0]['line'] . ' ]';
			Log::write($string);
		});

		//异常退出检查
		register_shutdown_function(function() use($fid) {
			self:: send_error_response($fid, '502 system error', '系统非正常退出');
		});

		//未找到类文件
		if (!is_file(APP_PATH . '/App/Controller/' . ucfirst($controller) . '.class.php'))
			return self:: send_error_response($fid, '404 file not fount', 'class "' . $controller . '" not fount');

		$class = '\\App\\Controller\\' . ucfirst($controller);
		$handel = new $class();
		//类继承错误
		if (($handel instanceof Controller) == false)
			return self:: send_error_response($fid, '501 system error', '系统文件错误');

		try {
			$handel->_set_request($request);
			if (method_exists($handel, $action) == false)
				return self:: send_error_response($fid, '404 file not fount', 'method "' . $action . '" not fount');
			$handel->$action();
		} catch (Exception $exc) {
			return self:: send_error_response($fid, '503 system error', '系统错误');
		}

		$output = $response->output($handel->outPut);
		event_buffer_write($GLOBALS['hq_buffers'][$fid], $output, strlen($output));
		//stream_socket_sendto($GLOBALS['hq_connections'][$fid], $output);
		unset($request);
		unset($response);
		unset($handel);
	}

	public static function send_error_response($fid, $http_code, $http_body, $content_type = 'text/html;charset=utf-8')
	{
		if (!$GLOBALS['hq_connections'] || !$GLOBALS['hq_connections'][$fid] || !$GLOBALS['hq_buffers'] || !$GLOBALS['hq_buffers'][$fid]) {
			unset($GLOBALS['hq_buffers'][$fid]);
			unset($GLOBALS['hq_connections'][$fid]);
			return false;
		}

		$len = strlen($http_body);
		$http_response = <<<EOF
HTTP/1.1 $http_code
Server: lxc-blog/1.0 (PHP)
Content-Type: $content_type
Connection: keep-alive
Content-Length: $len

$http_body
EOF;
		stream_socket_sendto($GLOBALS['hq_connections'][$fid], $http_response);
		return true;
	}

	/**
	 * 处理静态资源文件
	 * @param type $fid
	 * @param type $filename
	 */
	private static function send_file($fid, $filename)
	{
		$get_http_response = function ($content_type, $len, $cons, $http_code = '200 OK') {
			return $http_response = <<<EOF
HTTP/1.1 $http_code
Server: lxc-blog/1.0 (PHP)
Content-Type: ${content_type}
Connection: keep-alive
Content-Length: ${len}

$cons
EOF;
		};

		if (!file_exists($filename)) {
			$cons = '<h1>file not found</h1>';
			$http_response = $get_http_response('text/html', strlen($cons), $cons);
			stream_socket_sendto($GLOBALS['hq_connections'][$fid], $http_response);
			return false;
		}

		$len = filesize($filename);
		$cons = file_get_contents($filename);
		$content_type = self::get_mime($filename);
		$http_response = $get_http_response($content_type, $len, $cons);

		event_buffer_write($GLOBALS['hq_buffers'][$fid], $http_response, strlen($http_response));
		//stream_socket_sendto($GLOBALS['hq_connections'][$fid], $http_response);
	}

	public static function get_mime($filename)
	{
		$extension = strtolower(pathinfo($filename, PATHINFO_EXTENSION));
		switch ($extension) {
			case 'css':
				return 'text/css';
			case 'js':
				return 'application/javascript';
			case 'jpg':
			case 'jpeg':
				return 'image/jpg';
			case 'png':
				return 'image/png';
			case 'gif':
				return 'image/gif';
			default :
				return mime_content_type($filename) ?: 'text/html';
		}
	}

}
